Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: stackoverflow in ReadFrom #925

Conversation

romainmenke
Copy link
Contributor

@romainmenke romainmenke commented Nov 21, 2023

Thank you for contributing to Coraza WAF, your effort is greatly appreciated
Before submitting check if what you want to add to coraza list meets quality standards before sending pull request. Thanks!

Make sure that you've checked the boxes below before you submit PR:


#923 introduced a stackoverflow when the value passed to ReadFrom does not implement the io.WriterTo interface.

From the go stdlib source :

// copyBuffer is the actual implementation of Copy and CopyBuffer.
// if buf is nil, one is allocated.
func copyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) {
	// If the reader has a WriteTo method, use it to do the copy.
	// Avoids an allocation and a copy.
	if wt, ok := src.(WriterTo); ok {
		return wt.WriteTo(dst)
	}
	// Similarly, if the writer has a ReadFrom method, use it to do the copy.
	if rt, ok := dst.(ReaderFrom); ok {
		return rt.ReadFrom(src)
	}

If the first optimization can run no stackoverflow will happen.
But if the src does not implement io.WriterTo it will go to a second optimization.

In our use case it triggers a stackoverflow by calling itself.

There might be other ways to fix this and any suggestions are welcome!
I chose to erase all interfaces from the ResponseWriter except io.Writer.

This forces io.Copy to use Write(), which was the intended behavior.

Copy link

codecov bot commented Nov 21, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (a95ea5f) 82.57% compared to head (eeda3b7) 82.57%.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #925   +/-   ##
=======================================
  Coverage   82.57%   82.57%           
=======================================
  Files         160      160           
  Lines        8988     8988           
=======================================
  Hits         7422     7422           
  Misses       1317     1317           
  Partials      249      249           
Flag Coverage Δ
default 77.64% <100.00%> (ø)
examples 26.56% <0.00%> (ø)
ftw 47.01% <0.00%> (ø)
ftw-multiphase 49.21% <0.00%> (ø)
tinygo 75.14% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@romainmenke romainmenke marked this pull request as ready for review November 21, 2023 10:15
@romainmenke romainmenke requested a review from a team as a code owner November 21, 2023 10:15
@jcchavezs
Copy link
Member

jcchavezs commented Nov 21, 2023

I really appreciate the fact thart you cover with tests the fixes. In both PR I took the time to run the tests without the fix and confirmed the failure. Thanks a lot!

2023/11/21 11:52:49 http: superfluous response.WriteHeader call
2023/11/21 11:52:49 http: superfluous response.WriteHeader call
runtime: goroutine stack exceeds 1000000000-byte limit
runtime: sp=0x140201e0380 stack=[0x140201e0000, 0x140401e0000]
fatal error: stack overflow

@jcchavezs jcchavezs requested a review from anuraaga November 21, 2023 10:54
Copy link
Member

@fzipi fzipi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix!

@fzipi fzipi changed the title fix stackoverflow in ReadFrom fix: stackoverflow in ReadFrom Nov 21, 2023
@jcchavezs jcchavezs merged commit 4c7f918 into corazawaf:main Nov 27, 2023
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants